Тестирование внутренних методов с PHPUnit и runkit
PHPUnit хороший инструмент для тестирования PHP-кода. Но у него есть существенные ограничения влияющие его использование рядовыми программистами. Я даже не говорю об установке. Дело в том что юнит-тесты подразумевают
public function methodIWantToTest(){
$s='';
for($i=1;$i<10;$i++){
$s.=$this->innerMethodIWantToAvoidCalling($i);
}
return $s;
}
Это серъёзная проблема, ведь редко какой сложный метод обходится без вызова внутренних. Один из выходов — использовать новый instance этого же класса, и с помощью моков сымитировать поведение внутренней переменной (фактически запрещая использования $this). Моки конечно полезные, но я нехочу из-за ограничений фреймворка для тестирования менять свой код в нео птимальную сторону, добавляя выделение памяти под объект который уже и так создан. Поэтому..
Runkit
Runkit это экспериментальное расширение для php, позволяющее перезаписывать структуру классов на лету, что собственно нам и надо, потому что стандартный Reflection просто создаёт новые классы, а нам надо совместить существующий код с перезаписью внутреннего метода сделав из него заглушку (stub).
Самое неприятное тут это установка, потому что обычный pecl-install не работает и приходится делать checkout из репозитория с локальной установкой, потом копировать файл расширения (so/dll), прописывать в php.ini. Ну и потом у меня были опять проблемы из-за того что я использую не стандартный php на маке, а тот что в MAMP.
В итоге, после того как я инициализировал объ ект от класса, я просто перезаписываю его внутреннюю функцию на постоянно возвращаемое значение которое мне надо:
runkit_method_redefine('MyClassName','innerMethodIWantToAvoidCalling','','return "someFixedValue";',RUNKIT_ACC_PUBLIC);
Это конечно не так хорошо как динамический мок, но лучше чем не тестировать методы высокого уровня вообще
См. также..